import logging
import os
from typing import Any, List, Dict, Optional

from mcp.server.fastmcp import FastMCP

# Import exceptions
from excel_mcp.exceptions import (
    ValidationError,
    WorkbookError,
    SheetError,
    DataError,
    FormattingError,
    CalculationError,
    PivotError,
    ChartError
)

# Import from excel_mcp package with consistent _impl suffixes
from excel_mcp.validation import (
    validate_formula_in_cell_operation as validate_formula_impl,
    validate_range_in_sheet_operation as validate_range_impl
)
from excel_mcp.chart import create_chart_in_sheet as create_chart_impl
from excel_mcp.workbook import get_workbook_info
from excel_mcp.data import write_data
from excel_mcp.pivot import create_pivot_table as create_pivot_table_impl
from excel_mcp.tables import create_excel_table as create_table_impl
from excel_mcp.sheet import (
    copy_sheet,
    delete_sheet,
    rename_sheet,
    merge_range,
    unmerge_range,
    get_merged_ranges,
)

# Get project root directory path for log file path.
# When using the stdio transmission method,
# relative paths may cause log files to fail to create
# due to the client's running location and permission issues,
# resulting in the program not being able to run.
# Thus using os.path.join(ROOT_DIR, "excel-mcp.log") instead.

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
LOG_FILE = os.path.join(ROOT_DIR, "excel-mcp.log")

# Initialize EXCEL_FILES_PATH variable without assigning a value
EXCEL_FILES_PATH = None

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[
        # Referring to https://github.com/modelcontextprotocol/python-sdk/issues/409#issuecomment-2816831318
        # The stdio mode server MUST NOT write anything to its stdout that is not a valid MCP message.
        logging.FileHandler(LOG_FILE)
    ],
)
logger = logging.getLogger("excel-mcp")
# Initialize FastMCP server
mcp = FastMCP(
    "excel-mcp",
    version="0.1.5",
    description="Excel MCP Server for manipulating Excel files",
    dependencies=["openpyxl>=3.1.5"],
    env_vars={
        "EXCEL_FILES_PATH": {
            "description": "Path to Excel files directory",
            "required": False,
            "default": EXCEL_FILES_PATH
        }
    }
)

def get_excel_path(filename: str) -> str:
    """Get full path to Excel file.
    
    Args:
        filename: Name of Excel file
        
    Returns:
        Full path to Excel file
    """
    # If filename is already an absolute path, return it
    if os.path.isabs(filename):
        return filename

    # Check if in SSE mode (EXCEL_FILES_PATH is not None)
    if EXCEL_FILES_PATH is None:
        # Must use absolute path
        raise ValueError(f"Invalid filename: {filename}, must be an absolute path when not in SSE mode")

    # In SSE mode, if it's a relative path, resolve it based on EXCEL_FILES_PATH
    return os.path.join(EXCEL_FILES_PATH, filename)

@mcp.tool()
def apply_formula(
    filepath: str,
    sheet_name: str,
    cell: str,
    formula: str,
) -> str:
    """
    在Excel单元格中应用公式
    
    将Excel公式写入指定单元格，并进行验证。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        cell: 目标单元格地址（如：A1, B2）
        formula: Excel公式（如：=SUM(A1:A10), =B1*C1）
        
    返回值:
        操作结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        # First validate the formula
        validation = validate_formula_impl(full_path, sheet_name, cell, formula)
        if isinstance(validation, dict) and "error" in validation:
            return f"Error: {validation['error']}"
            
        # If valid, apply the formula
        from excel_mcp.calculations import apply_formula as apply_formula_impl
        result = apply_formula_impl(full_path, sheet_name, cell, formula)
        return result["message"]
    except (ValidationError, CalculationError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error applying formula: {e}")
        raise

@mcp.tool()
def validate_formula_syntax(
    filepath: str,
    sheet_name: str,
    cell: str,
    formula: str,
) -> str:
    """
    验证Excel公式语法
    
    检查Excel公式语法是否正确，但不实际应用到单元格。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        cell: 目标单元格地址（如：A1, B2）
        formula: 要验证的Excel公式（如：=SUM(A1:A10)）
        
    返回值:
        验证结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = validate_formula_impl(full_path, sheet_name, cell, formula)
        return result["message"]
    except (ValidationError, CalculationError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error validating formula: {e}")
        raise

@mcp.tool()
def format_range(
    filepath: str,
    sheet_name: str,
    start_cell: str,
    end_cell: Optional[str] = None,
    bold: bool = False,
    italic: bool = False,
    underline: bool = False,
    font_size: Optional[int] = None,
    font_color: Optional[str] = None,
    bg_color: Optional[str] = None,
    border_style: Optional[str] = None,
    border_color: Optional[str] = None,
    number_format: Optional[str] = None,
    alignment: Optional[str] = None,
    wrap_text: bool = False,
    merge_cells: bool = False,
    protection: Optional[Dict[str, Any]] = None,
    conditional_format: Optional[Dict[str, Any]] = None
) -> str:
    """
    格式化单元格区域
    
    对指定的单元格区域应用各种格式设置，包括字体、颜色、边框等。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址（如：A1）
        end_cell: 结束单元格地址（可选，如：C3。为空时只格式化单个单元格）
        bold: 是否加粗，默认False
        italic: 是否斜体，默认False
        underline: 是否下划线，默认False
        font_size: 字体大小（可选，如：12）
        font_color: 字体颜色（可选，如：FF0000表示红色）
        bg_color: 背景颜色（可选，如：FFFF00表示黄色）
        border_style: 边框样式（可选，如：thin, thick）
        border_color: 边框颜色（可选，如：000000表示黑色）
        number_format: 数字格式（可选，如：0.00, #,##0）
        alignment: 对齐方式（可选，如：center, left, right）
        wrap_text: 是否自动换行，默认False
        merge_cells: 是否合并单元格，默认False
        protection: 保护设置（可选，字典格式）
        conditional_format: 条件格式设置（可选，字典格式）
        
    返回值:
        格式化结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.formatting import format_range as format_range_func
        
        # Convert None values to appropriate defaults for the underlying function
        format_range_func(
            filepath=full_path,
            sheet_name=sheet_name,
            start_cell=start_cell,
            end_cell=end_cell,  # This can be None
            bold=bold,
            italic=italic,
            underline=underline,
            font_size=font_size,  # This can be None
            font_color=font_color,  # This can be None
            bg_color=bg_color,  # This can be None
            border_style=border_style,  # This can be None
            border_color=border_color,  # This can be None
            number_format=number_format,  # This can be None
            alignment=alignment,  # This can be None
            wrap_text=wrap_text,
            merge_cells=merge_cells,
            protection=protection,  # This can be None
            conditional_format=conditional_format  # This can be None
        )
        return "Range formatted successfully"
    except (ValidationError, FormattingError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error formatting range: {e}")
        raise

@mcp.tool()
def read_data_from_excel(
    filepath: str,
    sheet_name: str,
    start_cell: str = "A1",
    end_cell: Optional[str] = None,
    preview_only: bool = False
) -> str:
    """
    从Excel工作表读取数据
    
    读取指定区域的数据，包含单元格元数据和数据验证规则信息。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址，默认"A1"
        end_cell: 结束单元格地址（可选，未指定时自动扩展到有数据的区域）
        preview_only: 是否仅返回预览数据，默认False
        
    返回值:
        包含结构化单元格数据的JSON字符串，每个单元格包括：地址、值、行号、列号和验证信息
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.data import read_excel_range_with_metadata
        result = read_excel_range_with_metadata(
            full_path, 
            sheet_name, 
            start_cell, 
            end_cell
        )
        if not result or not result.get("cells"):
            return "No data found in specified range"
            
        # Return as formatted JSON string
        import json
        return json.dumps(result, indent=2, default=str)
        
    except Exception as e:
        logger.error(f"Error reading data: {e}")
        raise

@mcp.tool()
def write_data_to_excel(
    filepath: str,
    sheet_name: str,
    data: List[List],
    start_cell: str = "A1",
) -> str:
    """
    向Excel工作表写入数据
    
    将二维列表数据写入Excel工作表的指定位置。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        data: 要写入的数据，格式为二维列表，子列表代表行
        start_cell: 起始写入单元格地址，默认"A1"
        
    返回值:
        写入结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = write_data(full_path, sheet_name, data, start_cell)
        return result["message"]
    except (ValidationError, DataError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error writing data: {e}")
        raise

@mcp.tool()
def create_workbook(filepath: str) -> str:
    """
    创建新的Excel工作簿
    
    在指定路径创建一个新的Excel文件。
    
    参数:
        filepath: 新工作簿的文件路径（绝对路径或相对路径）
        
    返回值:
        创建结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.workbook import create_workbook as create_workbook_impl
        create_workbook_impl(full_path)
        return f"Created workbook at {full_path}"
    except WorkbookError as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error creating workbook: {e}")
        raise

@mcp.tool()
def create_worksheet(filepath: str, sheet_name: str) -> str:
    """
    在工作簿中创建新工作表
    
    在现有Excel文件中添加一个新的工作表。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 新工作表的名称
        
    返回值:
        创建结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.workbook import create_sheet as create_worksheet_impl
        result = create_worksheet_impl(full_path, sheet_name)
        return result["message"]
    except (ValidationError, WorkbookError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error creating worksheet: {e}")
        raise

@mcp.tool()
def create_chart(
    filepath: str,
    sheet_name: str,
    data_range: str,
    chart_type: str,
    target_cell: str,
    title: str = "",
    x_axis: str = "",
    y_axis: str = ""
) -> str:
    """
    在工作表中创建图表
    
    基于指定数据区域创建各种类型的图表。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        data_range: 数据区域（如：A1:C10）
        chart_type: 图表类型（如：column, bar, line, pie, scatter）
        target_cell: 图表放置的目标单元格位置（如：E1）
        title: 图表标题，默认为空
        x_axis: X轴标题，默认为空
        y_axis: Y轴标题，默认为空
        
    返回值:
        图表创建结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = create_chart_impl(
            filepath=full_path,
            sheet_name=sheet_name,
            data_range=data_range,
            chart_type=chart_type,
            target_cell=target_cell,
            title=title,
            x_axis=x_axis,
            y_axis=y_axis
        )
        return result["message"]
    except (ValidationError, ChartError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error creating chart: {e}")
        raise

@mcp.tool()
def create_pivot_table(
    filepath: str,
    sheet_name: str,
    data_range: str,
    rows: List[str],
    values: List[str],
    columns: Optional[List[str]] = None,
    agg_func: str = "mean"
) -> str:
    """
    在工作表中创建数据透视表
    
    基于指定数据区域创建数据透视表，支持多种聚合函数。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        data_range: 数据源区域（如：A1:D100）
        rows: 行字段列表（列名数组）
        values: 值字段列表（用于计算的列名数组）
        columns: 列字段列表（可选，列名数组）
        agg_func: 聚合函数，默认"mean"（可选：sum, count, mean, max, min）
        
    返回值:
        数据透视表创建结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = create_pivot_table_impl(
            filepath=full_path,
            sheet_name=sheet_name,
            data_range=data_range,
            rows=rows,
            values=values,
            columns=columns or [],
            agg_func=agg_func
        )
        return result["message"]
    except (ValidationError, PivotError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error creating pivot table: {e}")
        raise

@mcp.tool()
def create_table(
    filepath: str,
    sheet_name: str,
    data_range: str,
    table_name: Optional[str] = None,
    table_style: str = "TableStyleMedium9"
) -> str:
    """
    创建Excel原生表格
    
    将指定数据区域转换为Excel原生表格，支持筛选、排序等功能。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        data_range: 数据区域（如：A1:D10）
        table_name: 表格名称（可选，未指定时自动生成）
        table_style: 表格样式，默认"TableStyleMedium9"
        
    返回值:
        表格创建结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = create_table_impl(
            filepath=full_path,
            sheet_name=sheet_name,
            data_range=data_range,
            table_name=table_name,
            table_style=table_style
        )
        return result["message"]
    except DataError as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error creating table: {e}")
        raise

@mcp.tool()
def copy_worksheet(
    filepath: str,
    source_sheet: str,
    target_sheet: str
) -> str:
    """
    复制工作表
    
    在同一工作簿内复制一个工作表到新的工作表。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        source_sheet: 源工作表名称
        target_sheet: 目标工作表名称（新创建）
        
    返回值:
        复制结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = copy_sheet(full_path, source_sheet, target_sheet)
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error copying worksheet: {e}")
        raise

@mcp.tool()
def delete_worksheet(
    filepath: str,
    sheet_name: str
) -> str:
    """
    删除工作表
    
    从工作簿中删除指定的工作表。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 要删除的工作表名称
        
    返回值:
        删除结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = delete_sheet(full_path, sheet_name)
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error deleting worksheet: {e}")
        raise

@mcp.tool()
def rename_worksheet(
    filepath: str,
    old_name: str,
    new_name: str
) -> str:
    """
    重命名工作表
    
    修改工作表的名称。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        old_name: 当前工作表名称
        new_name: 新的工作表名称
        
    返回值:
        重命名结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = rename_sheet(full_path, old_name, new_name)
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error renaming worksheet: {e}")
        raise

@mcp.tool()
def get_workbook_metadata(
    filepath: str,
    include_ranges: bool = False
) -> str:
    """
    获取工作簿元数据信息
    
    获取工作簿的详细信息，包括工作表列表、区域信息等。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        include_ranges: 是否包含区域信息，默认False
        
    返回值:
        包含工作簿元数据的字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = get_workbook_info(full_path, include_ranges=include_ranges)
        return str(result)
    except WorkbookError as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error getting workbook metadata: {e}")
        raise

@mcp.tool()
def merge_cells(filepath: str, sheet_name: str, start_cell: str, end_cell: str) -> str:
    """
    合并单元格
    
    将指定区域的单元格合并为一个单元格。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址（如：A1）
        end_cell: 结束单元格地址（如：C3）
        
    返回值:
        合并结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = merge_range(full_path, sheet_name, start_cell, end_cell)
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error merging cells: {e}")
        raise

@mcp.tool()
def unmerge_cells(filepath: str, sheet_name: str, start_cell: str, end_cell: str) -> str:
    """
    取消合并单元格
    
    将已合并的单元格区域拆分为独立的单元格。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址（如：A1）
        end_cell: 结束单元格地址（如：C3）
        
    返回值:
        取消合并结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        result = unmerge_range(full_path, sheet_name, start_cell, end_cell)
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error unmerging cells: {e}")
        raise

@mcp.tool()
def get_merged_cells(filepath: str, sheet_name: str) -> str:
    """
    获取已合并的单元格信息
    
    返回工作表中所有已合并单元格的区域信息。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        
    返回值:
        已合并单元格区域信息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        return str(get_merged_ranges(full_path, sheet_name))
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error getting merged cells: {e}")
        raise

@mcp.tool()
def copy_range(
    filepath: str,
    sheet_name: str,
    source_start: str,
    source_end: str,
    target_start: str,
    target_sheet: Optional[str] = None
) -> str:
    """
    复制单元格区域
    
    将一个单元格区域复制到另一个位置，可以在同一工作表或不同工作表之间复制。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 源工作表名称
        source_start: 源区域起始单元格地址（如：A1）
        source_end: 源区域结束单元格地址（如：C3）
        target_start: 目标区域起始单元格地址（如：E1）
        target_sheet: 目标工作表名称（可选，未指定时使用源工作表）
        
    返回值:
        复制结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.sheet import copy_range_operation
        result = copy_range_operation(
            full_path,
            sheet_name,
            source_start,
            source_end,
            target_start,
            target_sheet or sheet_name  # Use source sheet if target_sheet is None
        )
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error copying range: {e}")
        raise

@mcp.tool()
def delete_range(
    filepath: str,
    sheet_name: str,
    start_cell: str,
    end_cell: str,
    shift_direction: str = "up"
) -> str:
    """
    删除单元格区域
    
    删除指定的单元格区域，并按指定方向移动剩余单元格。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址（如：A1）
        end_cell: 结束单元格地址（如：C3）
        shift_direction: 移动方向，默认"up"（可选：up, left）
        
    返回值:
        删除结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from excel_mcp.sheet import delete_range_operation
        result = delete_range_operation(
            full_path,
            sheet_name,
            start_cell,
            end_cell,
            shift_direction
        )
        return result["message"]
    except (ValidationError, SheetError) as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error deleting range: {e}")
        raise

@mcp.tool()
def validate_excel_range(
    filepath: str,
    sheet_name: str,
    start_cell: str,
    end_cell: Optional[str] = None
) -> str:
    """
    验证Excel区域有效性
    
    检查指定的单元格区域是否存在且格式正确。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        start_cell: 起始单元格地址（如：A1）
        end_cell: 结束单元格地址（可选，如：C3）
        
    返回值:
        验证结果消息字符串
    """
    try:
        full_path = get_excel_path(filepath)
        range_str = start_cell if not end_cell else f"{start_cell}:{end_cell}"
        result = validate_range_impl(full_path, sheet_name, range_str)
        return result["message"]
    except ValidationError as e:
        return f"Error: {str(e)}"
    except Exception as e:
        logger.error(f"Error validating range: {e}")
        raise

@mcp.tool()
def get_data_validation_info(
    filepath: str,
    sheet_name: str
) -> str:
    """
    获取工作表中的所有数据验证规则
    
    此工具帮助识别哪些单元格区域设置了验证规则以及应用了什么类型的验证。
    
    参数:
        filepath: Excel文件路径（绝对路径或相对路径）
        sheet_name: 工作表名称
        
    返回值:
        包含工作表中所有验证规则的JSON字符串
    """
    try:
        full_path = get_excel_path(filepath)
        from openpyxl import load_workbook
        from excel_mcp.cell_validation import get_all_validation_ranges
        
        wb = load_workbook(full_path, read_only=False)
        if sheet_name not in wb.sheetnames:
            return f"Error: Sheet '{sheet_name}' not found"
            
        ws = wb[sheet_name]
        validations = get_all_validation_ranges(ws)
        wb.close()
        
        if not validations:
            return "No data validation rules found in this worksheet"
            
        import json
        return json.dumps({
            "sheet_name": sheet_name,
            "validation_rules": validations
        }, indent=2, default=str)
        
    except Exception as e:
        logger.error(f"Error getting validation info: {e}")
        raise

async def run_sse():
    """Run Excel MCP server in SSE mode."""
    # Assign value to EXCEL_FILES_PATH in SSE mode
    global EXCEL_FILES_PATH
    EXCEL_FILES_PATH = os.environ.get("EXCEL_FILES_PATH", "./excel_files")
    # Create directory if it doesn't exist
    os.makedirs(EXCEL_FILES_PATH, exist_ok=True)
    
    try:
        logger.info(f"Starting Excel MCP server with SSE transport (files directory: {EXCEL_FILES_PATH})")
        await mcp.run_sse_async()
    except KeyboardInterrupt:
        logger.info("Server stopped by user")
    except Exception as e:
        logger.error(f"Server failed: {e}")
        raise
    finally:
        logger.info("Server shutdown complete")

async def run_streamable_http():
    """Run Excel MCP server in streamable HTTP mode."""
    # Assign value to EXCEL_FILES_PATH in streamable HTTP mode
    global EXCEL_FILES_PATH
    EXCEL_FILES_PATH = os.environ.get("EXCEL_FILES_PATH", "./excel_files")
    # Create directory if it doesn't exist
    os.makedirs(EXCEL_FILES_PATH, exist_ok=True)
    
    try:
        logger.info(f"Starting Excel MCP server with streamable HTTP transport (files directory: {EXCEL_FILES_PATH})")
        await mcp.run_streamable_http_async()
    except KeyboardInterrupt:
        logger.info("Server stopped by user")
    except Exception as e:
        logger.error(f"Server failed: {e}")
        raise
    finally:
        logger.info("Server shutdown complete")

def run_stdio():
    """Run Excel MCP server in stdio mode."""
    # No need to assign EXCEL_FILES_PATH in stdio mode
    
    try:
        logger.info("Starting Excel MCP server with stdio transport")
        mcp.run(transport="stdio")
    except KeyboardInterrupt:
        logger.info("Server stopped by user")
    except Exception as e:
        logger.error(f"Server failed: {e}")
        raise
    finally:
        logger.info("Server shutdown complete")